package com.lzw.breezeNovel.webApp.service.impl.video;




import com.lzw.breezeNovel.model.entity.pojo.video.VideoLike;
import com.lzw.breezeNovel.webApp.mapper.user.UserInfoMapper;
import com.lzw.breezeNovel.webApp.mapper.video.ShortVideoMapper;
import com.lzw.breezeNovel.webApp.mapper.video.VideoLikeMapper;
import com.lzw.breezeNovel.webApp.service.impl.common.AsyncService;
import com.lzw.breezeNovel.webApp.service.video.VideoLikeService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author 清风明月
 * @Package com.lzw.breezeNovel.webApp.service.impl.video
 * @date 2025/3/23
 * @description 视频点赞
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class VideoLikeServiceImpl implements VideoLikeService {

      /**
       * 注入mapper
       */
       @Autowired
       private VideoLikeMapper videoLikeMapper;
     /**
      * 注入redis客户端
      */
     @Autowired
     private RedissonClient redissonClient;
    /**
     * 注入redis
     */
    @Autowired
     private StringRedisTemplate stringRedisTemplate;
    /**
     * 注入短视频的表
     */
    @Autowired
    private ShortVideoMapper shortVideoMapper;

    /**
     * 注入异步服务
     */
    @Autowired
    private AsyncService asyncService;

    /**
     * 注入用户mapper
     */
    @Autowired
    private UserInfoMapper userInfoMapper;



    /**
     * 进行点赞
     * @param shortId
     * @param userId
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
      public void like(Long shortId, Long userId) {
         //创建锁名称
         String keyName = "video:like:" + shortId + ":" + userId;
         //进行加锁处理
         RLock lock = redissonClient.getLock(keyName);
         //加锁
         try{
             //尝试获取说 -> 加锁时间1000毫秒
             boolean iskey = lock.tryLock(3000, 10000, TimeUnit.MILLISECONDS);
             //判断是否获取到了
             if(iskey)
             {
                 //出现数据库判断是否被点赞
                 Boolean islike =  videoLikeMapper.isLike(shortId,userId) > 0;
                 //判断是否存在
                 if(islike)
                 {
                     //存在则进行取消点赞
                     videoLikeMapper.unlike(shortId,userId);
                     //同部到redis里面
                     stringRedisTemplate.opsForHash().delete(getRedisKey(shortId), String.valueOf(userId));
                 }else{
                     //不存在则进行点赞
                     VideoLike videoLike = new VideoLike();
                     //设置视频id
                     videoLike.setVideoId(shortId);
                     //设置用户id
                     videoLike.setUserId(userId);
                     //进行点赞
                     videoLikeMapper.like(videoLike);
                     //并且更新到短视频表里面
                     shortVideoMapper.updateLikeCount(shortId);
                     //异步更新用户的点赞数
                     asyncService.updateUserLikeCount(shortId,0);
                     //异步新增用户的点赞表
                     asyncService.addUserLike(shortId,userId,0);
                     //同步到redis里面
                     stringRedisTemplate.opsForHash().put(getRedisKey(shortId), String.valueOf(userId), "true");
                 }
             }else {
                 // 获取锁失败，可以抛出异常或者重试
                 throw new RuntimeException("获取锁失败");
             }
         }catch (Exception e)
         {
             log.error("点赞异常");
         }finally {
             //释放锁
             lock.unlock();
         }
     }




    /**
     * 取消点赞
     * @param shortId
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unlike(Long shortId, Long userId) {
        //创建锁名称
        String keyName = "video:like:" + shortId + ":" + userId;
        //进行加锁处理
        RLock lock = redissonClient.getLock(keyName);
        try {
            //尝试获取说 -> 加锁时间1000毫秒
            boolean isLock = lock.tryLock(3000, 10000, TimeUnit.MILLISECONDS);
            //判断是否成功
            if(isLock)
            {
                //判断是否被点赞
                Boolean isLike = videoLikeMapper.isLike(shortId,userId) > 0;
                if(isLike)
                {
                    //取消点赞
                    videoLikeMapper.unlike(shortId,userId);
                    //更新到短视频表里面
                    shortVideoMapper.updateLikeCountReduce(shortId);
                    //同步到redis里面
                    stringRedisTemplate.opsForHash().delete(getRedisKey(shortId), String.valueOf(userId));
                    //异步更新用户的点赞数
                    asyncService.updateUserLikeCount(shortId,1);
                    //异步删除用户的点赞表
                    asyncService.addUserLike(shortId,userId,1);
                }
            }else {
                // 获取锁失败，可以抛出异常或者重试
                throw new RuntimeException("获取锁失败");
            }

        }catch (Exception e)
        {
            log.error("取消点赞异常");
        }finally {
            //释放锁
            lock.unlock();
        }

    }




    /**
     * 获取 Redis 缓存的键
     *
     * @param shortId 短视频ID
     * @return Redis 键
     */
    @NotNull
    @Contract(pure = true)
    private String getRedisKey(Long shortId) {
        return "video:like:" + shortId;
    }

    /**
     * 同步 Redis 缓存到数据库
     */
    public void syncRedisToDatabase() {
        // 获取所有视频的点赞缓存
        Set<String> keys = stringRedisTemplate.keys("video:like:*");
        if (keys != null && !keys.isEmpty()) {
            for (String key : keys) {
                // 获取当前视频的所有点赞用户
                Map<Object, Object> likes = stringRedisTemplate.opsForHash().entries(key);
                // 提取视频ID
                Long shortId = Long.valueOf(key.replace("video:like:", ""));
                for (Map.Entry<Object, Object> entry : likes.entrySet()) {
                    // 提取用户ID
                    String userIdStr = entry.getKey().toString();
                    Long userId = Long.valueOf(userIdStr);
                    // 检查数据库中是否存在该点赞记录
                    boolean exists = videoLikeMapper.isLike(userId, shortId) > 0;
                    System.out.println(exists);
                    if (!exists) {
                        // 如果不存在，插入新的点赞记录
                        VideoLike videoLike = new VideoLike();
                        videoLike.setUserId(userId);
                        videoLike.setVideoId(shortId);
                        videoLike.setCreatedTime(new Date());
                        videoLikeMapper.like(videoLike);
                    }
                }
            }
        }
    }
}
